home *** CD-ROM | disk | FTP | other *** search
/ Aminet 15 / Aminet 15 - Nov 1996.iso / Aminet / comm / bbs / s342q16.lha / Cit_Qwk.c < prev    next >
C/C++ Source or Header  |  1996-08-29  |  48KB  |  1,900 lines

  1. /************************************************************************/
  2. /*
  3. * AsgQWK.c
  4. * QWIK off-line reader for Asgarde-86.
  5. * Modified for the Citadel 68K
  6. */
  7. /************************************************************************/
  8. /************************************************************************/
  9. /** history */
  10. /*
  11. * 93Sep15 GSM  Created.
  12. * 94OCT21 AFP  Modifications for Citadel-68K
  13. */
  14. /************************************************************************/
  15. #include "ctdl.h"
  16. #include "sysdep.h"
  17. #include "slist.h"
  18. /************************************************************************/
  19. /** Contents */
  20. /**/
  21. /** * QWKmain              Main entry to QWK routines. */
  22. /** * QWKUserConfig        QWK user configuration menu.*/
  23. /** * ScanRooms            Room selection menu.*/
  24. /** * UpdateLastRead*/
  25. /** * CreateQWKPacket*/
  26. /** * ExtractAndAdd*/
  27. /** * OkToSend*/
  28. /** * menus*/
  29. /** * qwkglobalreplace*/
  30. /** * qwkReadDate*/
  31. /** * qwkReadTime*/
  32. /** * RepReadDate*/
  33. /** * RepReadTime*/
  34. /** * ResetRooms*/
  35. /** * ArchQWK*/
  36. /** * InputREPPacket*/
  37. /** * ImportQWKPacket*/
  38. /** * CleanUpPacket*/
  39. /************************************************************************/
  40. #define DoFree(p)       if ((p) != NULL)  { free(p);   }
  41. #define VERSION         "V0.1a68k"
  42. /************************************************************************/
  43. /*
  44. * external variable declarations in LOGEDIT.C
  45. */
  46. /************************************************************************/
  47. extern CONFIG cfg;
  48. extern LogTable *logTab;          /** * RAM index of pippuls */
  49. extern logBuffer logBuf;          /** * Pippul buffer */
  50. extern aRoom roomBuf;
  51. extern MessageBuffer *msgBuf;     /** * Message buffer */
  52. extern MessageBuffer *tempMess;   /**  * Message buffer */
  53. extern NetBuffer netBuf;
  54. extern rTable *roomTab;
  55. extern NetTable *netTab;
  56. extern FILE *logfl;               /**  log file descriptor **/
  57. extern FILE *roomfl;
  58. extern FILE *netfl;
  59. extern struct floor *FloorTab;
  60. extern char NotForgotten;
  61. extern char onConsole;
  62. extern char haveCarrier;
  63. extern char outFlag;              /** * will be one of the above */
  64. extern AN_UNSIGNED crtColumn;     /** * where are we on screen now? */
  65. char noStop;
  66. extern long InChatTime;
  67. extern char loggedIn;
  68. extern int thisLog;
  69. extern char *READ_ANY;
  70. extern char FileTransStat;
  71. extern FILE *upfd;
  72. static char *MonthTab[] =
  73.   {
  74.   "JANUARY", "FEBRUARY", "MARCH", "APRIL", "MAY", "JUNE",
  75.   "JULY", "AUGUST", "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER"
  76.  
  77.   };
  78. SYS_FILE  tempname;
  79. SYS_FILE  tempFile;
  80. int       totconf,
  81. totfnd,
  82. tottoyou;
  83. unsigned char qwkbuf[128];
  84. long      currentsector;
  85. FILE     *qwkindfd,
  86. *qwkmsgfd,
  87. *qwkctlfd,
  88. *qwkpersfd;
  89. struct qwkheader
  90.   {
  91.   unsigned char status;
  92.   unsigned char number[7];
  93.   unsigned char date[8];
  94.   unsigned char time[5];
  95.   unsigned char to[25];
  96.   unsigned char from[25];
  97.   unsigned char subject[25];
  98.   unsigned char password[12];
  99.   unsigned char ref_no[8];
  100.   unsigned char size[6];
  101.   unsigned char active;
  102.   unsigned int conf;
  103.   unsigned int logical_msgno;
  104.   unsigned char nettag;
  105.  
  106.   };
  107. /*
  108. *
  109. * * the important stuff from the header
  110. */
  111. /*
  112. * true header format, only fields I use
  113. */
  114. struct qwkdefinition
  115.   {
  116.   char      YourOwn;
  117.   char      ResetBBSMsg;
  118.   char      NewFileScan;
  119.   char      FileDate[8];
  120.   char      Bulletins;
  121.   int       MaxPacket;
  122.   int       MaxRoom;
  123.   char      UpProtocol;
  124.   char      DownProtocol;
  125.   char      Archiver;
  126.   char      Hangafterupload;
  127.  
  128.   };
  129. struct qwkdefinition qwkdef;
  130. typedef struct
  131.   {
  132.   int       Selected;
  133.   MSG_NUMBER OldLastMessageNo;
  134.   MSG_NUMBER LastMessageNo;
  135.   MSG_NUMBER CurrentLastMessageNo;
  136.   int       AlternateConferenceNo;
  137.  
  138.   }
  139. QwkRoom;
  140. typedef struct
  141.   {
  142.   int       messagesfound;
  143.   int       messagestoyou;
  144.  
  145.   }
  146. UsedQwkRoom;
  147. QwkRoom  *QwkRooms;               /** RAM index of rooms */
  148. UsedQwkRoom *UsedQwkRooms;
  149. #ifdef ANSI_PROTOTYPING
  150. char      QWKmain(void);
  151. void      QWKUserConfig(void);
  152. void      ScanRooms(void);
  153. void      UpdateLastRead(void);
  154. void      CreateQWKPacket(void);
  155. void      ExtractAndAdd(int room);
  156. char      OkToSend(void);
  157. void      menus(void);
  158. void      qwkglobalreplace(char *buf, char *qwkold);
  159. void      qwkReadDate(char *date, char *datestr);
  160. void      qwkReadTime(char *time, char *timestr);
  161. void      RepReadDate(char *date, char *datestr);
  162. void      RepReadTime(char *time, char *timestr);
  163. void      ResetRooms(void);
  164. long      ArchQWK(void);
  165. void      InputREPPacket(void);
  166. void      ImportQWKPacket(void);
  167. void      CleanUpPacket(void);
  168. #endif
  169. /**
  170.   itoa(number,string,base);
  171.   number - number to convert to the requested base
  172.   string - destination string for number
  173.   base   - conversion base
  174. **/
  175. void itoa(int number, char *string, int base);
  176. void itoa(int number, char *string, int base)
  177.   {
  178.   sprintf(string,"%d",number);  /** cheap shortcut...*/
  179.   }
  180.  
  181.  
  182. /************************************************************************/
  183. /*
  184. * QWKmain() main controller.
  185. */
  186. /************************************************************************/
  187. char
  188. QWKmain()
  189.   {
  190.   FILE     *qwklogfd;
  191.   char      HasLog;
  192.   char      tempStr[20];
  193.   int       rover;
  194.   int       saveroom;
  195.   extern int thisRoom;
  196.  
  197.   saveroom = thisRoom;
  198.   mPrintf("\n Citadel QWK Mail Reader %s\n %s\n ", VERSION, COPYRIGHT);
  199.   if (!loggedIn)
  200.     {
  201.     mPrintf("Must log in to use Citadel QWK Mail reader!\n ");
  202.     return GOOD_SELECT;
  203.  
  204.     }
  205.   QwkRooms = (QwkRoom *) GetDynamic(MAXROOMS * (sizeof(*QwkRooms)));
  206.   UsedQwkRooms = (UsedQwkRoom *) GetDynamic(MAXROOMS * (sizeof(*UsedQwkRooms)));
  207.   HasLog = FALSE;
  208.   sprintf(tempStr, "qwklog.%03d", thisLog);
  209. /*  makeSysName(tempname, tempStr, &cfg.QWKFilesArea); */
  210.   makeSysName(tempname, tempStr, &cfg.holdArea);
  211.   if ((qwklogfd = fopen(tempname, "rb")) != NULL)
  212.     {
  213.     if (fread(&qwkdef, sizeof qwkdef, 1, qwklogfd) == 1)
  214.       {
  215.       HasLog = TRUE;
  216.       fread(QwkRooms, (sizeof(*QwkRooms)) * MAXROOMS, 1, qwklogfd);
  217.  
  218.       }
  219.     fclose(qwklogfd);
  220.  
  221.     }
  222.   if (HasLog == FALSE)
  223.     {
  224.     qwkdef.YourOwn = TRUE;
  225.     qwkdef.NewFileScan = FALSE;
  226.     strcpy(qwkdef.FileDate, "12/31/99");
  227.     qwkdef.Bulletins = FALSE;
  228.     qwkdef.MaxPacket = 10000;       /* maximum packet size */
  229.     qwkdef.MaxRoom =   MAXROOMS;    /* cfg.QWKMAXROOM;  */
  230.     qwkdef.UpProtocol = 0;
  231.     qwkdef.DownProtocol = 0;
  232.     qwkdef.Archiver = 1;
  233.     qwkdef.Hangafterupload = FALSE;
  234.     for (rover = 0; rover < MAXROOMS; rover++)
  235.       {
  236.       QwkRooms[rover].Selected = 0;
  237.       QwkRooms[rover].OldLastMessageNo = 0l;
  238.       QwkRooms[rover].LastMessageNo =
  239.       logBuf.lbvisit[logBuf.lbgen[rover] & CALLMASK];
  240.       QwkRooms[rover].CurrentLastMessageNo = 0l;
  241.       QwkRooms[rover].AlternateConferenceNo = 0;
  242.  
  243.       }
  244.  
  245.     }
  246.   menus();
  247.   sprintf(tempStr, "qwklog.%03d", thisLog);
  248.   /**** makeSysName(tempname, tempStr, &cfg.QWKFilesArea); ****/
  249.   makeSysName(tempname, tempStr, &cfg.holdArea);
  250.   if ((qwklogfd = fopen(tempname, "wb")) != NULL)
  251.     {
  252.     if (fwrite(&qwkdef, sizeof qwkdef, 1, qwklogfd) == 1)
  253.       {
  254.       HasLog = TRUE;
  255.       fwrite(QwkRooms, (sizeof(*QwkRooms)) * MAXROOMS, 1, qwklogfd);
  256.  
  257.       }
  258.     fclose(qwklogfd);
  259.  
  260.     }
  261.   free(QwkRooms);
  262.   free(UsedQwkRooms);
  263.   getRoom(saveroom);
  264.   return GOOD_SELECT;
  265.  
  266.   }
  267. /************************************************************************/
  268. /*
  269. * QWKUserConfig() various settings for users.
  270. */
  271. /************************************************************************/
  272. void
  273. QWKUserConfig()
  274.   {
  275.   char      done = FALSE;
  276.   char      letter,
  277.   letter1;
  278.   long      sessioncheck;
  279.   do
  280.     {
  281.     mPrintf("\n THOR QWK Mail Reader configuration menu:\n ");
  282.     mPrintf("                              Current setting\n ");
  283.     mPrintf("[C]onfigure conferences       (shows when selecting)\n ");
  284.     mPrintf("[R]eset high message pointers\n ");
  285.     mPrintf("[S]end your own messages      %s\n ",
  286.     qwkdef.YourOwn ? "Yes" : "No");
  287.     /*
  288.     * mPrintf("[N]ew files scan              %s\n ",
  289.  qwkdef.NewFileScan ?
  290.     * "Yes" : "No");
  291.  mPrintf("[D]ate for new files          %s\n ",
  292.     * qwkdef.FileDate);
  293.  mPrintf("[I]nclude new bulletins       %s\n ",
  294.     * qwkdef.Bulletins ? "Yes" : "No");
  295.     */ mPrintf("[M]aximum packet sizes        %3d/%3d\n ", qwkdef.MaxPacket, qwkdef.MaxRoom);
  296.     /*
  297.     * mPrintf("[A]ttachment size limit       0K/Your attachments only\n ");
  298.     */ mPrintf("[T]ransfer protocol-upload    %s\n ",
  299.     FindProtoName(qwkdef.UpProtocol));
  300.     mPrintf("                   -download    %s\n ",
  301.     FindProtoName(qwkdef.DownProtocol));
  302.     mPrintf("[P]acker (archiver)           %s\n ",
  303.     GetCompEnglish(qwkdef.Archiver));
  304.     /*
  305.     * mPrintf("[F]ormat for packets          QWK\n ");
  306.     */ mPrintf("[G]oodbye after upload        %s\n ",
  307.     qwkdef.Hangafterupload ? "Yes" : "No");
  308.     mPrintf("[H]elp with configuration\n ");
  309.     mPrintf("[Q]uit THOR QWK Configuration menu\n ");
  310.     sessioncheck = 0; /* chkTimeSince(USER_SESSION) - InChatTime; */
  311.     /*
  312.     if (sessionLimit > 0)
  313.     mPrintf("You have been on for %lu minutes, and have %lu minutes left.\n ",
  314.     (sessioncheck / 60), (((sessionLimit * 60) - sessioncheck) / 60));
  315.     */
  316.     mPrintf("\n CONFIGURE MENU [C R S M T P G H Q]: ");
  317.     letter1 = toUpper(iChar());
  318.     mPrintf("\n ");
  319.     switch (letter1)
  320.       {
  321.       case 'C':
  322.       ScanRooms();
  323.       break;
  324.       case 'R':
  325.       ResetRooms();
  326.       break;
  327.       case 'S':
  328.       qwkdef.YourOwn = !qwkdef.YourOwn;
  329.       break;
  330.       /*
  331.       * case 'N':
  332.  qwkdef.NewFileScan = !qwkdef.NewFileScan;
  333.  break;
  334.  case
  335.       * 'I':
  336.  qwkdef.Bulletins = !qwkdef.Bulletins;
  337.  break;
  338.  case 'A':
  339.       * mPrintf("Not used at this time\n ");
  340.  break;
  341.       */ case 'T':
  342.       tempMess->mbtext[0] = NULL;
  343.       UpProtsEnglish(tempMess->mbtext);
  344.       mPrintf("\n%s\n Enter upload protocol: ", tempMess->mbtext);
  345.       letter = toUpper(iChar());
  346.       mPrintf("\n ");
  347.       if ((qwkdef.UpProtocol = FindProtocolCode(letter, TRUE)) == -1)
  348.         {
  349.         mPrintf("invalid protocol, setting to zmodem\n ");
  350.         qwkdef.UpProtocol = FindProtocolCode('Z', TRUE);
  351.  
  352.         }
  353.       tempMess->mbtext[0] = NULL;
  354.       DownProtsEnglish(tempMess->mbtext);
  355.       mPrintf("%s\n Enter download protocol: ", tempMess->mbtext);
  356.       letter = toUpper(iChar());
  357.       mPrintf("\n ");
  358.       if ((qwkdef.DownProtocol = FindProtocolCode(letter, FALSE)) == -1)
  359.         {
  360.         mPrintf("invalid protocol, setting to zmodem\n ");
  361.         qwkdef.DownProtocol = FindProtocolCode('Z', FALSE);
  362.  
  363.         }
  364.       break;
  365.       case 'P':
  366.       qwkdef.Archiver = GetUserCompression();
  367.       break;
  368.       /*
  369.       * case 'D':  break;
  370.       */
  371.       case 'M':
  372.       qwkdef.MaxPacket = getNumber("QWKTMS", 0, 10000); /*cfg.QWKMAXPACKET); */
  373.       qwkdef.MaxRoom   = getNumber("QWKMPC", 0, MAXROOMS); /*cfg.QWKMAXROOM);*/
  374.       break;
  375.       case 'G':
  376.       qwkdef.Hangafterupload = !qwkdef.Hangafterupload;
  377.       break;
  378.       /*
  379.       * case 'F':  mPrintf("Not used at this time\n "); break;
  380.       */
  381.       case 'H':
  382.       tutorial("qwkconf.hlp", TRUE);
  383.       break;
  384.       case 'Q':
  385.       done = TRUE;
  386.       break;
  387.       default:
  388.       done = TRUE;
  389.       break;
  390.  
  391.       }
  392.     if (!done)
  393.     writeSysTab();
  394.  
  395.     }
  396.   while (!done);
  397.  
  398.   }
  399. /************************************************************************/
  400. /*
  401. * ScanRooms() Room selection setup routine.
  402. */
  403. /************************************************************************/
  404. #define ALL 0
  405. #undef  SELECTED
  406. #define SELECTED 1
  407. void
  408. ScanRooms()
  409.   {
  410.   int       rover,
  411.   currentstart,
  412.   i,
  413.   newstart,
  414.   done,
  415.   innerdone,
  416.   lpcnt;
  417.   int       lines,
  418.   pagelength,
  419.   chosen;
  420.   char      tempStr[10],
  421.   scanflag,
  422.   letter[5];
  423.   newstart = 0;
  424.   currentstart = 0;
  425.   i = 0;
  426.   /*  if (logBuf.lbscrnlngth == 0) */
  427.   pagelength = 23;
  428.   /*  else
  429.   pagelength = logBuf.lbscrnlngth;
  430.   */
  431.   done = FALSE;
  432.   scanflag = ALL;
  433.   do
  434.     {
  435.     lines = 0;
  436.     for (rover = currentstart; rover < MAXROOMS; rover++)
  437.       {
  438.       /*
  439.       * deep breath ... should rewrite this, prime example of programming
  440.       * via accretion.
  441.       */
  442.       if ((KnownRoom(rover) || (NotForgotten &&
  443.       roomTab[rover].rtflags.INUSE &&
  444.       (aide && (cfg.BoolFlags.aideSeeAll || onConsole) &&
  445.       (!roomTab[rover].rtflags.INVITE || onConsole)))))
  446.         {
  447.         if (QwkRooms[rover].Selected)
  448.         sprintf(tempStr, "(%7.7lu)", QwkRooms[rover].LastMessageNo);
  449.         else
  450.         memset(tempStr, NULL, 7);
  451.         if ((scanflag == SELECTED && QwkRooms[rover].Selected) ||
  452.         (scanflag == ALL))
  453.           {
  454.           mPrintf("%3d)%s%-20s %9s ", rover,
  455.           (QwkRooms[rover].Selected ? "*" : " "),
  456.           roomTab[rover].rtname,
  457.           tempStr);
  458.           i++;
  459.           if (i == 2)
  460.             {
  461.             mPrintf("\n ");
  462.             i = 0;
  463.             lines = lines + 1;
  464.  
  465.             }
  466.           if (lines == (pagelength - 5))
  467.             {
  468.             newstart = rover + 1;
  469.             rover = MAXROOMS;
  470.  
  471.             }
  472.  
  473.           }
  474.  
  475.         }
  476.  
  477.       }
  478.     innerdone = FALSE;
  479.     do
  480.       {
  481.       /*
  482.       * mPrintf("You have been on for %d minutes, and have %d minutes left.\n ",
  483.       * ontime, maxtime);
  484.       */
  485.       if (newstart < MAXROOMS)
  486.       mPrintf(" - More below, use [+] to view\n ");
  487.       mPrintf("CONFERENCE MENU:\n Enter #, [*] select all, [L]ist, [+]Next, [-]Previous, List [A]ll\n ");
  488.       mPrintf("List [O]nly selected, [R]everse selections, [T]op of conferences, or [Q]uit? ");
  489.       getString("", letter, 5, 0);
  490.       if (strlen(letter) == 0)
  491.       letter[0] = '?';
  492.       for (lpcnt = 0; lpcnt < strlen(letter); lpcnt++)
  493.       letter[lpcnt] = toUpper(letter[lpcnt]);
  494.       mPrintf("\n ");
  495.       switch (letter[0])
  496.         {
  497.         case 'T':
  498.         currentstart = 0;
  499.         innerdone = TRUE;
  500.         break;
  501.         case '+':
  502.         currentstart = newstart;
  503.         if (currentstart > MAXROOMS)
  504.         currentstart = MAXROOMS - (pagelength - 5);
  505.         innerdone = TRUE;
  506.         break;
  507.         case '-':
  508.         currentstart = currentstart - (pagelength - 5);
  509.         if (currentstart < 0)
  510.         currentstart = 0;
  511.         innerdone = TRUE;
  512.         break;
  513.         case 'L':
  514.         innerdone = TRUE;
  515.         break;
  516.         case 'A':
  517.         scanflag = ALL;
  518.         break;
  519.         case 'O':
  520.         scanflag = SELECTED;
  521.         break;
  522.         case 'Q':
  523.         done = TRUE;
  524.         innerdone = TRUE;
  525.         break;
  526.         case '*':
  527.         case 'R':
  528.         for (chosen = 0; chosen < MAXROOMS; chosen++)
  529.           {
  530.           if (KnownRoom(chosen) ||
  531.           (NotForgotten && roomTab[chosen].rtflags.INUSE &&
  532.           (aide && (cfg.BoolFlags.aideSeeAll || onConsole)) &&
  533.           (!roomTab[chosen].rtflags.INVITE || onConsole)))
  534.             {
  535.             if (!QwkRooms[chosen].Selected || letter[0] == '*')
  536.             QwkRooms[chosen].Selected = TRUE;
  537.             else
  538.             QwkRooms[chosen].Selected = FALSE;
  539.  
  540.             }
  541.  
  542.           }
  543.         break;
  544.         case '?':
  545.         mPrintf("Invalid selection. Try Again.\n ");
  546.         break;
  547.         default:
  548.         /*
  549.         * chosen = getNumber("QWKRMN", 0, MAXROOMS);
  550.         */
  551.         chosen = (int) atoi(letter);
  552.         if (KnownRoom(chosen) ||
  553.         (NotForgotten && roomTab[chosen].rtflags.INUSE &&
  554.         (aide && (cfg.BoolFlags.aideSeeAll || onConsole)) &&
  555.         (!roomTab[rover].rtflags.INVITE || onConsole)))
  556.           {
  557.           if (QwkRooms[chosen].Selected)
  558.           QwkRooms[chosen].Selected = FALSE;
  559.           else
  560.           QwkRooms[chosen].Selected = TRUE;
  561.  
  562.           }
  563.         else
  564.           {
  565.           mPrintf("Room(conference) not known or not in use.\n ");
  566.  
  567.           }
  568.         break;
  569.  
  570.         }
  571.  
  572.       }
  573.     while (!innerdone);
  574.  
  575.     }
  576.   while (!done);
  577.  
  578.   }
  579. /************************************************************************/
  580. /*
  581. * UpdateLastRead() Updates QWK message pointer structure.  Called
  582. */
  583. /*
  584. * only after a succesful download.
  585. */
  586. /************************************************************************/
  587. void
  588. UpdateLastRead()
  589.   {
  590.   int       rover;
  591.   for (rover = 0; rover < MAXROOMS; rover++)
  592.     {
  593.     if (UsedQwkRooms[rover].messagesfound > 0)
  594.       {
  595.       QwkRooms[rover].OldLastMessageNo = QwkRooms[rover].LastMessageNo;
  596.       QwkRooms[rover].LastMessageNo = QwkRooms[rover].CurrentLastMessageNo;
  597.       QwkRooms[rover].CurrentLastMessageNo = 0l;
  598.  
  599.       }
  600.  
  601.     }
  602.  
  603.   }
  604. /************************************************************************/
  605. /*
  606. * CreateQWKPacket() Scans all rooms for new messages and extracts
  607. */
  608. /*
  609. * them IF the room is selected.
  610. */
  611. /************************************************************************/
  612. void
  613. CreateQWKPacket()
  614.   {
  615.   int       rover;
  616.   int       year,  month,  day,  hours,  minutes,  seconds,  milli;
  617.   int         success;
  618.   char      tempstr[30],  tempstr2[30],  c;
  619.   long      packetSize;
  620.   getRawDate(&year, &month, &day, &hours, &minutes,
  621.   &seconds, &milli);
  622.   makeSysName(tempname, "messages.dat", &cfg.holdArea); /*QWKWorkArea); */
  623.   if ((qwkmsgfd = fopen(tempname, "wb")) == NULL)
  624.     {
  625.     crashout("Cannot Open messages data file!");
  626.  
  627.     }
  628.   memset(qwkbuf, ' ', 128);
  629.   sprintf(qwkbuf, "Produced by QMAIL...Copyright (c) 1987 by Sparkware. All Rights Reserved.");
  630.   success = strlen(qwkbuf);
  631.   qwkbuf[success] = ' ';
  632.   success = FALSE;
  633.   fwrite(qwkbuf, 128, 1, qwkmsgfd);
  634.   currentsector = 1;
  635.   makeSysName(tempname, "personal.ndx", &cfg.holdArea); /* QWKWorkArea); */
  636.   if ((qwkpersfd = fopen(tempname, "wb")) == NULL)
  637.     {
  638.     crashout("Cannot Open personal.ndx data file!");
  639.  
  640.     }
  641.   makeSysName(tempname, "control.dat", &cfg.holdArea); /* QWKWorkArea); */
  642.   if ((qwkctlfd = fopen(tempname, "wb")) == NULL)
  643.     {
  644.     crashout("Cannot Open control data file!");
  645.  
  646.     }
  647.   fputs((cfg.codeBuf + cfg.nodeName), qwkctlfd);
  648.   fputc('\r', qwkctlfd);
  649.   fputc(NEWLINE, qwkctlfd);
  650.   /* fputs((cfg.CityState + cfg.codeBuf), qwkctlfd); */
  651.   fputs("  ", qwkctlfd);
  652.   fputc('\r', qwkctlfd);
  653.   fputc(NEWLINE, qwkctlfd);
  654.   fputs((cfg.nodeId + cfg.codeBuf), qwkctlfd);
  655.   fputc('\r', qwkctlfd);
  656.   fputc(NEWLINE, qwkctlfd);
  657.   fputs(cfg.SysopName, qwkctlfd);
  658.   fputc('\r', qwkctlfd);
  659.   fputc(NEWLINE, qwkctlfd);
  660.   sprintf(tempstr, "0,%s", (cfg.codeBuf + cfg.nodeTitle));
  661.   fputs(tempstr, qwkctlfd);
  662.   fputc('\r', qwkctlfd);
  663.   fputc(NEWLINE, qwkctlfd);
  664.   sprintf(tempstr, "%02d-%02d-%04d,%02d:%02d:%02d", month, day, year,
  665.   hours, minutes, seconds);
  666.   fputs(tempstr, qwkctlfd);
  667.   fputc('\r', qwkctlfd);
  668.   fputc(NEWLINE, qwkctlfd);
  669.   sprintf(tempstr, "%s", strupr(logBuf.lbname));
  670.   fputs(tempstr, qwkctlfd);
  671.   fputc('\r', qwkctlfd);
  672.   fputc(NEWLINE, qwkctlfd);
  673.   fputs(" ", qwkctlfd);
  674.   fputc('\r', qwkctlfd);
  675.   fputc(NEWLINE, qwkctlfd);
  676.   fputs("0", qwkctlfd);
  677.   fputc('\r', qwkctlfd);
  678.   fputc(NEWLINE, qwkctlfd);
  679.   mPrintf("\n Preparing mail packet...\n ");
  680.   mPrintf("Press S to abort scan\n \n ");
  681.   mPrintf("Total message limit: %d\n ", qwkdef.MaxPacket);
  682.   mPrintf("Room(Conference) message limit: %d\n ", qwkdef.MaxRoom);
  683.   mPrintf("                                          High    Last    Number      To\n ");
  684.   mPrintf(" Number  Conference                    Message    Read     Found     You\n ");
  685.   mPrintf("------------------------------------------------------------------------\n ");
  686.   totfnd = 0;
  687.   totconf = 0;
  688.   outFlag = OUTOK;
  689.   for (rover = 0; rover < MAXROOMS && onLine() && outFlag == OUTOK; rover++)
  690.     {
  691.     if (rover == MAILROOM)
  692.       {
  693.       getRoom(rover);
  694.       fillMailRoom();   /*
  695.       * update room also
  696.       */
  697.  
  698.       }
  699.     UsedQwkRooms[rover].messagesfound = 0;
  700.     UsedQwkRooms[rover].messagestoyou = 0;
  701.     if (QwkRooms[rover].Selected && roomTab[rover].rtflags.INUSE)
  702.       {
  703.       mPrintf("   %3d     %-20s        %7.7lu %7.7lu ", rover,
  704.       roomTab[rover].rtname, roomTab[rover].rtlastMessage,
  705.       QwkRooms[rover].LastMessageNo);
  706.       ExtractAndAdd(rover);
  707.       mPrintf("    %5d   %5d\n ", UsedQwkRooms[rover].messagesfound,
  708.       UsedQwkRooms[rover].messagestoyou);
  709.       tottoyou += UsedQwkRooms[rover].messagestoyou;
  710.       mAbort();
  711.  
  712.       }
  713.  
  714.     }
  715.   if (outFlag == OUTOK)
  716.     {
  717.     mPrintf("Total messages found: %d\n ", totfnd);
  718.     /*
  719.     * Total new bulletins: 2
  720.     */
  721.     /*
  722.     * Collecting new files:  22 new files
  723.     */
  724.  
  725.     }
  726.   sprintf(tempstr, "%d", totfnd);
  727.   fputs(tempstr, qwkctlfd);
  728.   fputc('\r', qwkctlfd);
  729.   fputc(NEWLINE, qwkctlfd);
  730.   sprintf(tempstr, "%d", totconf - 1);
  731.   fputs(tempstr, qwkctlfd);
  732.   fputc('\r', qwkctlfd);
  733.   fputc(NEWLINE, qwkctlfd);
  734.   for (rover = 0; rover < MAXROOMS; rover++)
  735.     {
  736.     if (UsedQwkRooms[rover].messagesfound != 0)
  737.       {
  738.       sprintf(tempstr, "%d", rover);
  739.       fputs(tempstr, qwkctlfd);
  740.       fputc('\r', qwkctlfd);
  741.       fputc(NEWLINE, qwkctlfd);
  742.       fputs(roomTab[rover].rtname, qwkctlfd);
  743.       fputc('\r', qwkctlfd);
  744.       fputc(NEWLINE, qwkctlfd);
  745.  
  746.       }
  747.  
  748.     }
  749.   fputs("BULLETIN.QWK", qwkctlfd);
  750.   fputc('\r', qwkctlfd);
  751.   fputc(NEWLINE, qwkctlfd);
  752.   fputs("NEWS.QWK", qwkctlfd);
  753.   fputc('\r', qwkctlfd);
  754.   fputc(NEWLINE, qwkctlfd);
  755.   fputs("GOODBYE.QWK", qwkctlfd);
  756.   fputc('\r', qwkctlfd);
  757.   fputc(NEWLINE, qwkctlfd);
  758.   fclose(qwkctlfd);
  759.   fclose(qwkmsgfd);
  760.   fclose(qwkpersfd);
  761.   if (outFlag == OUTOK && totfnd > 0)
  762.     {
  763.     mPrintf("Would you like to receive this packet,\n ");
  764.     mPrintf("[Y]es, [N]o, [G]oodbye when done? ");
  765.     c = toUpper(iChar());
  766.     mPrintf("\n ");
  767.     switch (c)
  768.       {
  769.       case 'Y':
  770.       case 'G':
  771.       mPrintf("Packing QWK packet with %s\n ", GetCompEnglish(qwkdef.Archiver));
  772.       packetSize = ArchQWK();
  773.       mPrintf("Packet size: %lu bytes\n ", packetSize);
  774.       sprintf(tempstr, "%s.qwk", (cfg.codeBuf + cfg.nodeTitle));
  775.       mPrintf("Start your %s download of %s now\n ",
  776.       FindProtoName(qwkdef.DownProtocol), tempstr);
  777.  /*     strcpy(tempstr2, (cfg.codeBuf + cfg.QWKWorkArea.saDirname));*/
  778.       strcpy(tempstr2, (char *)&cfg.holdArea);
  779.       success = strlen(tempstr2);
  780.       tempstr2[success - 1] = NULL;
  781.       /*
  782.       * printf("%s\n", tempstr2);
  783.       */
  784.       if (chdir(tempstr2) != 0) printf("chdir failed!\n");
  785.       /*
  786.       * printf("%s\n", getcwd(NULL, 100));  iChar();
  787.       *
  788.       */
  789.       FileTransStat = FL_START;
  790.       TranFiles(qwkdef.DownProtocol,  FALSE);
  791.       if (c == 'G')  HangUp(TRUE);
  792.       /*
  793.       * printf("%d\n", FileTransStat);
  794.       */
  795.       if (FileTransStat == FL_SUCCESS)
  796.       UpdateLastRead();
  797.       break;
  798.  
  799.       }
  800.  
  801.     }
  802.   outFlag = OUTOK;
  803.   CleanUpPacket();
  804.   homeSpace();
  805.  
  806.   }
  807. /************************************************************************/
  808. /*
  809. * ExtractAndAdd() Reads the selected room for new messages and
  810. */
  811. /*
  812. * places them in the QWK packet in proper format.
  813. */
  814. /************************************************************************/
  815. #define LOADIT !NORMAL
  816. void
  817. ExtractAndAdd(int room)
  818.   {
  819.   union Converter
  820.     {
  821.     unsigned char uc[10];
  822.     unsigned int ui[5];
  823.     unsigned long ul[2];
  824.     float     f[2];
  825.     double    d[1];
  826.  
  827.     };
  828.   union Converter t;
  829.   char *pp, *qq;
  830.   int       sign,  exp;
  831.   struct qwkheader qwkhead;
  832.   int    length,  chrcnt,  blocks,  tempcheck,  tc;
  833.   SYS_FILE  tempname;
  834.   char     *mp;
  835.   char      nwlcp = 227;
  836.   int       i,  h,  j,  start,  finish,  increment;
  837.   MSG_NUMBER lowLim,  highLim,  msgNo,  MsgRead;
  838.   char        tempstr[50];
  839.   getRoom(room);
  840.   if (room == MAILROOM)
  841.   fillMailRoom();       /*
  842.   * update room also
  843.   */
  844.   start = 0;
  845.   finish = (room == MAILROOM) ? MAILSLOTS : MSGSPERRM;
  846.   increment = 1;
  847.   lowLim = QwkRooms[room].LastMessageNo + 1l;
  848.   highLim = cfg.newest;
  849.   if (cfg.oldest > lowLim)
  850.     {
  851.     lowLim = cfg.oldest;
  852.  
  853.     }
  854.   MsgRead = lowLim;
  855.   sprintf(tempstr, "%03d.ndx", room);
  856. /*  makeSysName(tempname, tempstr, &cfg.QWKWorkArea); */
  857.   makeSysName(tempname, tempstr, &cfg.holdArea);
  858.   if ((qwkindfd = fopen(tempname, "wb")) == NULL)
  859.     {
  860.     sprintf(tempstr, "Cannot create index file for conference %d", room);
  861.     crashout(tempstr);
  862.  
  863.     }
  864.   for (i = start; i != finish && (onLine()) &&
  865.   totfnd < qwkdef.MaxPacket && outFlag == OUTOK &&
  866.   UsedQwkRooms[room].messagesfound < qwkdef.MaxRoom; i++)
  867.     {
  868.     msgNo = (roomBuf.msg[i].rbmsgNo & S_MSG_MASK);
  869.     /**
  870.     * Now check to see if msg is in "to be read" range, OR if we are
  871.     * reading New AND the message is marked as SKIPPED (only happens in
  872.     * Mail).  Note at the moment we're not going to worry about net mode --
  873.     * we don't use this loop for sending Mail, although we do for other
  874.     * rooms.
  875.     */
  876.     if (
  877.     (msgNo >= lowLim && highLim >= msgNo)
  878.     )
  879.       {
  880.       noStop = LOADIT;
  881.       if (findMessage(roomBuf.msg[i].rbmsgLoc, msgNo, TRUE) &&
  882.       OkToSend())
  883.         {
  884.         noStop = NORMAL;
  885.         UsedQwkRooms[room].messagesfound++;
  886.         if (msgNo > MsgRead)
  887.         MsgRead = msgNo;
  888.         totfnd++;
  889.         memset(&qwkhead, ' ', 128);
  890.         sprintf(tempstr, "/\n /%c/", 227);
  891.         qwkglobalreplace(msgBuf->mbtext, tempstr);
  892.         sprintf(tempstr, "/\n/%c/", ' ');
  893.         qwkglobalreplace(msgBuf->mbtext, tempstr);
  894.         length = strlen(msgBuf->mbtext);
  895.         length = (length / 79) + length;
  896.         blocks = (length / 128) + 2;
  897.         qwkhead.status = ' ';
  898.         itoa(totfnd, qwkhead.number, 10);
  899.         tempcheck = strlen(qwkhead.number);
  900.         qwkhead.number[tempcheck] = ' ';
  901.         qwkReadDate(msgBuf->mbdate, qwkhead.date);
  902.         tempcheck = strlen(qwkhead.date);
  903.         qwkhead.date[tempcheck] = ' ';
  904.         qwkReadTime(msgBuf->mbtime, qwkhead.time);
  905.         tempcheck = strlen(qwkhead.time);
  906.         qwkhead.time[tempcheck] = ' ';
  907.         if (!msgBuf->mbto[0])
  908.         strcpy(qwkhead.to, "ALL");
  909.         else
  910.         strncpy(qwkhead.to, strupr(msgBuf->mbto), 25);
  911.         tempcheck = strlen(qwkhead.to);
  912.         qwkhead.to[tempcheck] = ' ';
  913.         if (strcmpi(msgBuf->mbto, logBuf.lbname) == SAMESTRING)
  914.         UsedQwkRooms[room].messagestoyou++;
  915.         if (!roomBuf.rbflags.ANON)
  916.  
  917.           strcpy(qwkhead.from, strupr(msgBuf->mbauth));
  918.           tempcheck = strlen(qwkhead.from);
  919.           qwkhead.from[tempcheck] = ' ';
  920.  
  921.           }
  922.  /*        strncpy(qwkhead.subject, msgBuf->mbSubj, 25); */
  923.         memset(qwkhead.subject, ' ', 25);
  924.         memset(qwkhead.password, ' ', 12);
  925.         itoa(UsedQwkRooms[room].messagesfound, qwkhead.ref_no, 10);
  926.         tempcheck = strlen(qwkhead.ref_no);
  927.         qwkhead.ref_no[tempcheck] = ' ';
  928.         itoa(blocks, qwkhead.size, 10);
  929.         tempcheck = strlen(qwkhead.size);
  930.         qwkhead.size[tempcheck] = ' ';
  931.         qwkhead.active = 225;
  932.         pp = (char *)room;
  933.         qq = (char *)qwkhead.conf;
  934.         qq[0] = pp[1];
  935.         qq[1] = pp[0];
  936.         qwkhead.conf = room;
  937.         qwkhead.logical_msgno = totfnd;
  938.         qwkhead.nettag = ' ';
  939.         currentsector++;
  940.         fwrite(&qwkhead, 128, 1, qwkmsgfd);
  941.         t.f[0] = (float) currentsector;
  942.         sign = t.uc[3] / 0x80;
  943.         exp = ((t.ui[1] >> 7) - 0x7f + 0x81) & 0xff;
  944.         t.ui[1] = (t.ui[1] & 0x7f) | (sign << 7) | (exp << 8);
  945.         fwrite(&t.f[0], 4, 1, qwkindfd);
  946.         fwrite(0, 1, 1, qwkindfd);
  947.         if (strcmpi(msgBuf->mbto, logBuf.lbname) == SAMESTRING)
  948.           {
  949.           fwrite(&t.f[0], 4, 1, qwkpersfd);
  950.           fwrite(0, 1, 1, qwkpersfd);
  951.  
  952.           }
  953.         mp = msgBuf->mbtext;
  954.         chrcnt = 0;
  955.         for (h = 1; h < blocks; h++)
  956.           {
  957.           memset(qwkbuf, ' ', 128);
  958.           for (j = 0; j < 128; j++)
  959.             {
  960.             if (*mp != NULL)
  961.               {
  962.               if (*mp == nwlcp)
  963.               chrcnt = 0;
  964.               if (j < 128)
  965.                 {
  966.                 qwkbuf[j] = *mp;
  967.                 chrcnt++;
  968.                 mp++;
  969.  
  970.                 }
  971.               if (chrcnt == 79)
  972.                 {
  973.                 tc = j;
  974.                 do
  975.                   {
  976.                   if (tc >= 0 && qwkbuf[tc] == ' ')
  977.                     {
  978.                     qwkbuf[tc] = 227;
  979.                     chrcnt = 0;
  980.  
  981.                     }
  982.                   else
  983.                     {
  984.                     chrcnt--;
  985.                     tc--;
  986.  
  987.                     }
  988.                   if (chrcnt == 45)
  989.                     {
  990.                     j++;
  991.                     qwkbuf[j] = 227;
  992.                     chrcnt = 0;
  993.  
  994.                     }
  995.  
  996.                   }
  997.                 while (chrcnt > 44);
  998.  
  999.                 }
  1000.  
  1001.               }
  1002.             else
  1003.               {
  1004.               qwkbuf[j] = 227;
  1005.               break;
  1006.  
  1007.               }
  1008.  
  1009.             }
  1010.           fwrite(qwkbuf, 128, 1, qwkmsgfd);
  1011.           currentsector++;
  1012.  
  1013.           }
  1014.  
  1015.         }
  1016.  
  1017.       }
  1018.  
  1019.     }
  1020.   fclose(qwkindfd);
  1021.   noStop = NORMAL;
  1022.   if (UsedQwkRooms[room].messagesfound == 0)
  1023.     {
  1024.     sprintf(tempstr, "%03d.ndx", room);
  1025.  /*   makeSysName(tempname, tempstr, &cfg.QWKWorkArea); */
  1026.     makeSysName(tempname, tempstr, &cfg.holdArea);
  1027.     unlink(tempname);
  1028.  
  1029.     }
  1030.   else
  1031.     {
  1032.     totconf++;
  1033.     QwkRooms[room].CurrentLastMessageNo = MsgRead;
  1034.  
  1035.     }
  1036.  
  1037.   }
  1038. /************************************************************************/
  1039. /*
  1040. * OkToSend() Checks the current message to make sure it is a
  1041. */
  1042. /*
  1043. * selected message to be sent.
  1044. */
  1045. /************************************************************************/
  1046. char
  1047. OkToSend()
  1048.   {
  1049.   /*
  1050.   * if ((strcmpi(msgBuf->mbauth, logBuf.lbname)==SAMESTRING) &&
  1051.   * qwkdef.YourOwn)
  1052.  return TRUE;
  1053.   */
  1054.   if ((strcmpi(msgBuf->mbauth, logBuf.lbname) == SAMESTRING) &&
  1055.   !qwkdef.YourOwn)
  1056.   return FALSE;
  1057.   return TRUE;
  1058.  
  1059.   }
  1060. /************************************************************************/
  1061. /*
  1062. * menus() Main menu routine.
  1063. */
  1064. /************************************************************************/
  1065. void
  1066. menus()
  1067.   {
  1068.   char      letter,
  1069.   done = FALSE;
  1070.   do
  1071.     {
  1072.     outFlag = OUTOK;
  1073.     mPrintf("\n \n Citadel-68K Offline Message Door (%s)\n ", VERSION);
  1074.     mPrintf("[D]ownload QWK packet\n ");
  1075.     mPrintf("[U]pload REP packet\n ");
  1076.     mPrintf("[C]onfigure your settings\n ");
  1077.     mPrintf("[H]elp with THOR\n ");
  1078.     mPrintf("[G]oodbye, hang up\n ");
  1079.     mPrintf("[Q]uit back to %s ", cfg.codeBuf + cfg.nodeTitle);
  1080.     letter = toUpper(iChar());
  1081.     mPrintf("\n ");
  1082.     switch (letter)
  1083.       {
  1084.       case 'C':
  1085.       QWKUserConfig();
  1086.       break;
  1087.       case 'D':
  1088.       CreateQWKPacket();
  1089.       break;
  1090.       case 'U':
  1091.       InputREPPacket();
  1092.       break;
  1093.       case 'H':
  1094.       tutorial("qwkmain.hlp", TRUE);
  1095.       break;
  1096.       case 'G':
  1097.       HangUp(TRUE);
  1098.       break;
  1099.       case 'Q':
  1100.       done = TRUE;
  1101.       break;
  1102.       default:
  1103.       done = TRUE;
  1104.       break;
  1105.  
  1106.       }
  1107.     if (!done)
  1108.     writeSysTab();
  1109.  
  1110.     }
  1111.   while (!done);
  1112.  
  1113.   }
  1114. /************************************************************************/
  1115. /*
  1116. * globalreplace()
  1117. */
  1118. /*
  1119. * Replace the first delimited string with the second delimited
  1120. */
  1121. /*
  1122. * string.  An optional repeat count precedes the 1st delimiter.
  1123. */
  1124. /*
  1125. * If a repeat count isn't given, it is assumed to be MAXTEXT+1.
  1126. */
  1127. /*
  1128. * The delimiter may be any character except a numeric character.
  1129. */
  1130. /************************************************************************/
  1131. void
  1132. qwkglobalreplace(char *buf, char *qwkold)
  1133.   {
  1134.   #define STRINGSIZE  (4*SECTSIZE)
  1135.   char       *p,
  1136.   *bufend,
  1137.   delim,
  1138.   *old,
  1139.   *new;
  1140.   int       i,
  1141.   cnt,
  1142.   oldlen,
  1143.   newlen,
  1144.   diff;
  1145.   if (!*qwkold)
  1146.   return;       /*
  1147.   * Quit if no string
  1148.   */
  1149.   cnt = (int) atoi(qwkold);
  1150.   if (!cnt)
  1151.   cnt = strlen(buf);
  1152.   p = qwkold;
  1153.   while (isdigit(*p))   /*
  1154.   * Skip over the count if any
  1155.   */
  1156.   p++;
  1157.   delim = *p;
  1158.   new = strchr(old = ++p, delim) + 1;
  1159.   p = strchr(new, delim);
  1160.   new[-1] =     /*
  1161.   * Terminate old string
  1162.   */
  1163.   *p = 0;       /*
  1164.   * Terminate new string
  1165.   */
  1166.   newlen = strlen(new);
  1167.   oldlen = strlen(old);
  1168.   diff = newlen - oldlen;
  1169.   if (!*old)
  1170.   /*  * keep dolts from entering a  */
  1171.    return;
  1172.         /*  * NULL as the search string.  */
  1173.   for (p = buf, i = cnt; bufend = buf + strlen(buf), p < bufend && i &&
  1174.   onLine() && !outFlag; p += newlen, i--)
  1175.     {
  1176.     p = matchString(p, old, bufend);
  1177.     if (!p)
  1178.     break;
  1179.     if (newlen > oldlen && diff >= (MAXTEXT - strlen(buf) - 1))
  1180.       {
  1181.       /*
  1182.       * mPrintf(" Buffer Full\n ");
  1183.       */
  1184.       break;
  1185.  
  1186.       }
  1187.     crtColumn = 1;
  1188.     /*
  1189.     * mPrintf("%4d\b\b\b\b", cnt-i);
  1190.     */
  1191.   /*  replace(p, new, oldlen, newlen); */
  1192.  
  1193.     }
  1194.   outFlag = OUTOK;
  1195.   /*
  1196.   * mPrintf(" Replaced %d", cnt -i);
  1197.  doCR();
  1198.   */
  1199.  
  1200.   }
  1201. /************************************************************************/
  1202. /*
  1203. * qwkReadDate()
  1204. */
  1205. /*
  1206. */
  1207. /*
  1208. * This function interprets the citadel date string and returns a
  1209. */
  1210. /*
  1211. * QWK formatted date string.
  1212. */
  1213. /************************************************************************/
  1214. void
  1215. qwkReadDate(char *date, char *datestr)
  1216.   {
  1217.   int       rover,
  1218.   found;
  1219.   int       year,
  1220.   month,
  1221.   day;
  1222.   label     mon;
  1223.   if (!date[0])
  1224.     {
  1225.     year = 90;
  1226.     month = 1;
  1227.     day = 1;
  1228.  
  1229.     }
  1230.   else
  1231.     {
  1232.     if (!isdigit(date[0]))
  1233.       {
  1234.       year = 90;
  1235.       month = 1;
  1236.       day = 1;
  1237.  
  1238.       }
  1239.     else
  1240.       {
  1241.       year = atoi(date);
  1242.       while (isdigit(*date))
  1243.       date++;
  1244.       for (rover = 0; isalpha(*date); date++, rover++)
  1245.       mon[rover] = toUpper(*date);
  1246.       mon[rover] = 0;
  1247.       if (rover == 0)
  1248.         {
  1249.         year = 90;
  1250.         month = 1;
  1251.         day = 1;
  1252.  
  1253.         }
  1254.       else
  1255.         {
  1256.         for (found = rover = 0; rover < NumElems(MonthTab); rover++)
  1257.         if (strncmp(mon, MonthTab[rover], strLen(mon)) == SAMESTRING)
  1258.           {
  1259.           found++;
  1260.           month = rover + 1;
  1261.  
  1262.           }
  1263.         if (found != 1)
  1264.         month = 1;
  1265.         if ((day = atoi(date)) == 0)
  1266.         day = 1;
  1267.  
  1268.         }
  1269.  
  1270.       }
  1271.  
  1272.     }
  1273.   sprintf(datestr, "%02d-%02d-%02d", month, day, year);
  1274.   return;
  1275.  
  1276.   }
  1277. /************************************************************************/
  1278. /*
  1279. * qwkReadTime()
  1280. */
  1281. /*
  1282. */
  1283. /*
  1284. * This function interprets the citadel time string and returns a
  1285. */
  1286. /*
  1287. * QWK formatted time string.
  1288. */
  1289. /************************************************************************/
  1290. void
  1291. qwkReadTime(char *time, char *timestr)
  1292.   {
  1293.   int   hours,  minutes;
  1294.   if (!time[0])
  1295.     {
  1296.     hours = 00;
  1297.     minutes = 00;
  1298.  
  1299.     }
  1300.   else
  1301.     {
  1302.     if (!isdigit(time[0]))
  1303.       {
  1304.       hours = 00;
  1305.       minutes = 00;
  1306.  
  1307.       }
  1308.     else
  1309.       {
  1310.       hours = atoi(time);
  1311.       while (isdigit(*time))
  1312.       time++;
  1313.       time++;
  1314.       minutes = atoi(time);
  1315.       while (isdigit(*time))
  1316.       time++;
  1317.       if (strchr(time, 'P') || strchr(time, 'p'))
  1318.       hours += 12;
  1319.  
  1320.       }
  1321.  
  1322.     }
  1323.   sprintf(timestr, "%02d:%02d", hours, minutes);
  1324.   return;
  1325.  
  1326.   }
  1327. /************************************************************************/
  1328. /*
  1329. * RepReadDate()
  1330. */
  1331. /*
  1332. */
  1333. /*
  1334. * This function interprets the QWK REP date string and returns a
  1335. */
  1336. /*
  1337. * Citadel formatted date string.
  1338. */
  1339. /************************************************************************/
  1340. void
  1341. RepReadDate(char *date, char *datestr)
  1342.   {
  1343.   char     *monthTab[13] =
  1344.     {
  1345.     "", "Jan", "Feb", "Mar",
  1346.     "Apr", "May", "Jun",
  1347.     "Jul", "Aug", "Sep",
  1348.     "Oct", "Nov", "Dec"
  1349.  
  1350.     };
  1351.   int       year,  month,  day;
  1352.   if (!date[0])
  1353.     {
  1354.     year = 0;
  1355.     month = 0;
  1356.     day = 0;
  1357.  
  1358.     }
  1359.   else
  1360.     {
  1361.     if (!isdigit(date[0]))
  1362.       {
  1363.       year = 0;
  1364.       month = 0;
  1365.       day = 0;
  1366.  
  1367.       }
  1368.     else
  1369.       {
  1370.       month = atoi(date);
  1371.       while (isdigit(*date))
  1372.       date++;
  1373.       date++;
  1374.       day = atoi(date);
  1375.       while (isdigit(*date))
  1376.       date++;
  1377.       date++;
  1378.       year = atoi(date);
  1379.       while (isdigit(*date))
  1380.       date++;
  1381.       date++;
  1382.  
  1383.       }
  1384.  
  1385.     }
  1386.   if (year != 0 && month != 0 && day != 0)
  1387.   sprintf(datestr, "%02d%3s%02d", year, monthTab[month - 1], day);
  1388.   else
  1389.   datestr[0] = NULL;
  1390.   return;
  1391.  
  1392.   }
  1393. /************************************************************************/
  1394. /*
  1395. * RepReadTime()
  1396. */
  1397. /*
  1398. */
  1399. /*
  1400. * This function interprets the QWK REP time string and returns a
  1401. */
  1402. /*
  1403. * Citadel formatted time string.
  1404. */
  1405. /************************************************************************/
  1406. void
  1407. RepReadTime(char *time, char *timestr)
  1408.   {
  1409.   int     hours,  minutes;
  1410.   if (!time[0])
  1411.     {
  1412.     hours = 00;
  1413.     minutes = 00;
  1414.  
  1415.     }
  1416.   else
  1417.     {
  1418.     if (!isdigit(time[0]))
  1419.       {
  1420.       hours = 00;
  1421.       minutes = 00;
  1422.  
  1423.       }
  1424.     else
  1425.       {
  1426.       hours = atoi(time);
  1427.       while (isdigit(*time))
  1428.       time++;
  1429.       time++;
  1430.       minutes = atoi(time);
  1431.       while (isdigit(*time))
  1432.       time++;
  1433.  
  1434.       }
  1435.  
  1436.     }
  1437.   if (hours != 0 && minutes != 0)
  1438.   sprintf(timestr, "%02d:%02d %s", (hours > 12) ? hours - 12 : hours,
  1439.   minutes, (hours > 12) ? "pm" : "am");
  1440.   else
  1441.   timestr[0] = NULL;
  1442.   return;
  1443.  
  1444.   }
  1445. /************************************************************************/
  1446. /*
  1447. * ResetRooms()
  1448. */
  1449. /*
  1450. */
  1451. /*
  1452. * This function is a menu system for selecting and reseting message
  1453. */
  1454. /*
  1455. * pointers for QWK packets.
  1456. */
  1457. /************************************************************************/
  1458. void
  1459. ResetRooms()
  1460.   {
  1461.   char      done = FALSE;
  1462.   char      letter1;
  1463.   int       rover;
  1464.   long      offset;
  1465.   outFlag = OUTOK;
  1466.   do
  1467.     {
  1468.     mPrintf("\n THOR QWK Mail Reader Message Reset menu:\n ");
  1469.     mPrintf("[0] Reset to 0 (all new)\n ");
  1470.     mPrintf("[1] Reset to newest number (all old)\n ");
  1471.     mPrintf("[2] Reset to beginning of previous call\n ");
  1472.     mPrintf("[3] Reset to last read pointers from BBS\n ");
  1473.     mPrintf("[4] Reset to newest number - inputed valued\n ");
  1474.     /*
  1475.     * mPrintf("[5] Upload %s.PTR file\n ", (cfg.codeBuf + cfg.nodeTitle));
  1476.     */
  1477.     mPrintf("[H]elp with message reset\n ");
  1478.     mPrintf("[Q]uit THOR QWK Mail Reader (c) reset menu\n ");
  1479.  /**   sessioncheck = chkTimeSince(USER_SESSION) - InChatTime;
  1480.     if (sessionLimit > 0)
  1481.     mPrintf("You have been on for %lu minutes, and have %lu minutes left.\n ",
  1482.     (sessioncheck / 60), (((sessionLimit * 60) - sessioncheck) / 60));
  1483.  **/
  1484.     mPrintf("\n RESET MENU [0 1 2 3 4 H Q]: ");
  1485.     letter1 = toUpper(iChar());
  1486.     mPrintf("\n ");
  1487.     switch (letter1)
  1488.       {
  1489.       case '0':
  1490.       for (rover = 0; rover < MAXROOMS; rover++)
  1491.         {
  1492.         QwkRooms[rover].LastMessageNo = 0l;
  1493.  
  1494.         }
  1495.       break;
  1496.       case '1':
  1497.       for (rover = 0; rover < MAXROOMS; rover++)
  1498.         {
  1499.         QwkRooms[rover].LastMessageNo = cfg.newest;
  1500.  
  1501.         }
  1502.       break;
  1503.       case '2':
  1504.       for (rover = 0; rover < MAXROOMS; rover++)
  1505.         {
  1506.         QwkRooms[rover].LastMessageNo =
  1507.         QwkRooms[rover].OldLastMessageNo;
  1508.  
  1509.         }
  1510.       break;
  1511.       case '3':
  1512.       for (rover = 0; rover < MAXROOMS; rover++)
  1513.         {
  1514.         QwkRooms[rover].LastMessageNo =
  1515.         logBuf.lbvisit[logBuf.lbgen[rover] & CALLMASK];
  1516.  
  1517.         }
  1518.       break;
  1519.       case '4':
  1520.       offset = getNumber("QWKNML", 1, cfg.MsgsPerrm);
  1521.       for (rover = 0; rover < MAXROOMS; rover++)
  1522.         {
  1523.         QwkRooms[rover].LastMessageNo =
  1524.         roomTab[rover].rtlastMessage - offset;
  1525.  
  1526.         }
  1527.       break;
  1528.       case '5':
  1529.       mPrintf("not active at this time\n ");
  1530.       break;
  1531.       case 'Q':
  1532.       done = TRUE;
  1533.       break;
  1534.       case 'H':
  1535.       default:
  1536.       tutorial("qwkreset.hlp", TRUE);
  1537.       break;
  1538.  
  1539.       }
  1540.  
  1541.     }
  1542.   while (!done);
  1543.   return;
  1544.  
  1545.   }
  1546. /************************************************************************/
  1547. /*
  1548. * ArchQWK()
  1549. */
  1550. /*
  1551. */
  1552. /*
  1553. * This function will archive all files from the QWKworkarea using
  1554. */
  1555. /*
  1556. * whatever archiving method the BBS supports and the user has
  1557. */
  1558. /*
  1559. * selected.  It will then return the size of the resulting file.
  1560. */
  1561. /************************************************************************/
  1562. long
  1563. ArchQWK()
  1564.   {
  1565.   FILE     *fbuf;
  1566.   char      tempStr[20],
  1567.   tempstr[30];
  1568.   long      fileSize = 0l;
  1569.   sprintf(tempStr, "%s.qwk", (cfg.codeBuf + cfg.nodeTitle));
  1570.   makeSysName(tempname, tempStr, &cfg.holdArea); /*QWKWorkArea);*/
  1571.   strcpy(tempstr, "*.*");
  1572.   makeSysName(tempFile, tempstr, &cfg.holdArea); /*QWKWorkArea);*/
  1573.   Compress(qwkdef.Archiver, tempFile, tempname);
  1574.   if ((fbuf = safeopen(tempname, READ_ANY)) != NULL)
  1575.     {
  1576.     totalBytes(&fileSize, fbuf);
  1577.     fclose(fbuf);
  1578.  
  1579.     }
  1580.   /*
  1581.   * printf("ArchQWK C1: %u, %s\n", fileSize, tempname); iChar();
  1582.   */
  1583.   return fileSize;
  1584.  
  1585.   }
  1586. /************************************************************************/
  1587. /*
  1588. * InputREPPacket()
  1589. */
  1590. /*
  1591. */
  1592. /*
  1593. * This function receive a file from the user into th QWLworkarea, and
  1594. */
  1595. /*
  1596. * then un-archive it using the method the user has selected in user
  1597. */
  1598. /*
  1599. * configuration.  And then it will call the import routine to import
  1600. */
  1601. /*
  1602. * the message into the message base.
  1603. */
  1604. /************************************************************************/
  1605. void
  1606. InputREPPacket()
  1607.   {
  1608.   char      tempstr[30],
  1609.   tempstr2[30],
  1610.   tempstr3[20];
  1611.   int       success;
  1612.   sprintf(tempstr, "%s.rep", (cfg.codeBuf + cfg.nodeTitle));
  1613.   sprintf(tempstr3, "%s.msg", (cfg.codeBuf + cfg.nodeTitle));
  1614.   mPrintf("Start your %s upload of %s now\n ",
  1615.   FindProtoName(qwkdef.UpProtocol), tempstr);
  1616.   strcpy(tempstr2,(char *)&cfg.holdArea); /*(cfg.codeBuf + cfg.QWKWorkArea.saDirname));*/
  1617.   success = strlen(tempstr2);
  1618.   tempstr2[success - 1] = NULL;
  1619.   if (chdir(tempstr2) != 0)  printf("chdir failed!\n");
  1620.   FileTransStat = FL_START;
  1621.   upLoad(qwkdef.UpProtocol, tempstr,FALSE);
  1622.   if (qwkdef.Hangafterupload)
  1623.   HangUp(TRUE);
  1624.   if (FileTransStat == FL_SUCCESS)
  1625.     {
  1626.     QWKDeCompress(qwkdef.Archiver, tempstr, tempstr3);
  1627.     homeSpace();
  1628.     ImportQWKPacket();
  1629.     strcpy(tempstr2,(char *)&cfg.holdArea); /*(cfg.codeBuf + cfg.QWKWorkArea.saDirname));*/
  1630.     success = strlen(tempstr2);
  1631.     tempstr2[success - 1] = NULL;
  1632.     if (chdir(tempstr2) != 0) printf("chdir failed!\n");
  1633.  
  1634.     }
  1635.   unlink(tempstr);
  1636.   unlink(tempstr3);
  1637.   homeSpace();
  1638.   return;
  1639.  
  1640.   }
  1641. /************************************************************************/
  1642. /*
  1643. * ImportQWKPacket()
  1644. */
  1645. /*
  1646. */
  1647. /*
  1648. * This function reads the files from the REP packet and places the
  1649. */
  1650. /*
  1651. * messages in the proper rooms in the message base.
  1652. */
  1653. /************************************************************************/
  1654. void
  1655. ImportQWKPacket()
  1656.   {
  1657.   struct qwkheader qwkhead;
  1658.   int       rover,
  1659.   chrcnt,
  1660.   blocks,
  1661.   tempcheck;
  1662.   SYS_FILE  tempname;
  1663.   char      nwlcp = 227;
  1664.   int     h,  j,  savemess;
  1665.   char   tempstr[50];
  1666.   char     *pc,
  1667.   allUpper;
  1668.   extern SListBase BadWords;
  1669.   extern char BadMessages[];
  1670.   sprintf(tempstr, "%s.msg", (cfg.codeBuf + cfg.nodeTitle));
  1671.   makeSysName(tempname, tempstr, &cfg.holdArea); /*QWKWorkArea); */
  1672.   if ((qwkmsgfd = fopen(tempname, "rb")) == NULL)
  1673.     {
  1674.     mPrintf("Cannot open MSG file from REP packet!\n ");
  1675.     return;
  1676.     /*
  1677.     * crashout(tempstr);
  1678.     */
  1679.  
  1680.     }
  1681.   fread(qwkbuf, sizeof qwkbuf, 1, qwkmsgfd);
  1682.   tempcheck = 1;
  1683.   do
  1684.     {
  1685.     memset(&qwkhead, ' ', 128);
  1686.     tempcheck = fread(&qwkhead, sizeof qwkhead, 1, qwkmsgfd);
  1687.     if (tempcheck == 1)
  1688.       {
  1689.       blocks = atoi(qwkhead.size);
  1690.       rover = qwkhead.conf;
  1691.       savemess = TRUE;
  1692.       if (rover < MAXROOMS && rover >= 0)
  1693.       getRoom(rover);
  1694.       else
  1695.         {
  1696.         rover = LOBBY;
  1697.         getRoom(LOBBY);
  1698.         savemess = FALSE;
  1699.  
  1700.         }
  1701.       if (!QwkRooms[rover].Selected)
  1702.       savemess = FALSE;
  1703.       ZeroMsgBuffer(msgBuf);
  1704.       /*
  1705.       * This is where we fill in the header information for the incoming
  1706.       * message, making sure to use the real name  or the handle name
  1707.       * from logbuf depending on the room's  fido aware status flag.   We
  1708.       * also need to get the room number out of the qwkhead.conf area,
  1709.       * make sure the date is in proper format and setup special checks
  1710.       * for the mail  room.
  1711.       */
  1712.       strCpy(msgBuf->mbroom, roomBuf.rbname);
  1713.       strcpy(msgBuf->mbauth, logBuf.lbname);
  1714.   /** setMisc();
  1715.       if (roomBuf.rbflags.FIDO)
  1716.         {
  1717.         if (logBuf.lbflags.FidoWrite)
  1718.         strcpy(msgBuf->mbauth, logBuf.lbRealname);
  1719.         else
  1720.         savemess = FALSE;
  1721.         memset(msgBuf->mbto, NULL, 26);
  1722.         strncpy(msgBuf->mbto, qwkhead.to, 25);
  1723.         memset(msgBuf->mbSubj, NULL, 73);
  1724.         strncpy(msgBuf->mbSubj, qwkhead.subject, 25);
  1725.  
  1726.         }
  1727.    **/
  1728.       strcpy(msgBuf->mbroom, roomBuf.rbname);
  1729.       if (rover == MAILROOM)
  1730.         {
  1731.         memset(msgBuf->mbto, NULL, 26);
  1732.         strncpy(msgBuf->mbto, qwkhead.to, 25);
  1733.         CleanEnd(msgBuf->mbto);
  1734.         if (!getRecipient())
  1735.         savemess = FALSE;
  1736.  
  1737.         }
  1738.       memset(tempstr, NULL, 20);
  1739.       strncpy(tempstr, qwkhead.date, 8);
  1740.       RepReadDate(tempstr, msgBuf->mbdate);
  1741.       memset(tempstr, NULL, 20);
  1742.       strncpy(tempstr, qwkhead.time, 5);
  1743.       RepReadTime(tempstr, msgBuf->mbtime);
  1744.       chrcnt = 0;
  1745.       for (h = 1; h < blocks; h++)
  1746.         {
  1747.         memset(qwkbuf, ' ', 128);
  1748.         tempcheck = fread(qwkbuf, sizeof qwkbuf, 1, qwkmsgfd);
  1749.         for (j = 0; j < 128; j++)
  1750.           {
  1751.           if (qwkbuf[j] != nwlcp)
  1752.           msgBuf->mbtext[chrcnt++] = qwkbuf[j];
  1753.           else
  1754.             {
  1755.             msgBuf->mbtext[chrcnt++] = NEWLINE;
  1756.             msgBuf->mbtext[chrcnt++] = ' ';
  1757.  
  1758.             }
  1759.           if (chrcnt > 7449)
  1760.             {
  1761.             msgBuf->mbtext[chrcnt++] = NULL;
  1762.             CleanEnd(msgBuf->mbtext);
  1763.             if (cfg.BoolFlags.NetScanBad)
  1764.               {
  1765.               if (rover != MAILROOM && SearchList(&BadWords, msgBuf->mbtext) != NULL)
  1766.                 {
  1767.                 extern char BadMessages[];
  1768.                 savemess = FALSE;
  1769.  
  1770.                 DiscardMessage( strlen(BadMessages)? BadMessages : "discard");
  1771.  
  1772.                 sPrintf(msgBuf->mbtext, "QWK message from %s @%s in %s discarded for decency reasons.",
  1773.                         msgBuf->mbauth, msgBuf->mboname,
  1774.                         (roomExists(msgBuf->mbroom)) ?
  1775.                         formRoom(roomExists(msgBuf->mbroom),FALSE, FALSE) :
  1776.                         msgBuf->mbroom); netResult(msgBuf->mbtext);
  1777.                 netResult(msgBuf->mbtext);
  1778.  
  1779.                 }
  1780.  
  1781.               }
  1782.             if (savemess)
  1783.               {
  1784.               for (pc = msgBuf->mbtext, allUpper = TRUE; *pc && allUpper; pc++)
  1785.                 {
  1786.                 if (toUpper(*pc) != *pc)
  1787.                 allUpper = FALSE;
  1788.  
  1789.                 }
  1790.               if (allUpper)
  1791.               fakeFullCase(msgBuf->mbtext);
  1792.               putMessage(&logBuf);
  1793.  
  1794.               }
  1795.             chrcnt = 0;
  1796.             memset(msgBuf->mbtext, NULL, MAXTEXT);
  1797.  
  1798.             }
  1799.  
  1800.           }
  1801.  
  1802.         }
  1803.       msgBuf->mbtext[chrcnt++] = NULL;
  1804.       CleanEnd(msgBuf->mbtext);
  1805.       if (cfg.BoolFlags.NetScanBad)
  1806.         {
  1807.         if (rover != MAILROOM && SearchList(&BadWords, msgBuf->mbtext) != NULL)
  1808.           {
  1809.           savemess = FALSE;
  1810.           DiscardMessage("discard");
  1811.           /*
  1812.           * sPrintf(msgBuf->mbtext, "QWK message from %s @%s in %s discarded for
  1813.           * decency reasons.", msgBuf->mbauth, msgBuf->mboname,
  1814.           * (roomExists(msgBuf->mbroom)) ? formRoom(roomExists(msgBuf->mbroom),
  1815.           * FALSE, FALSE) : msgBuf->mbroom); netResult(msgBuf->mbtext);
  1816.           */
  1817.           savemess = FALSE;
  1818.  
  1819.           }
  1820.  
  1821.         }
  1822.       if (savemess)
  1823.         {
  1824.         for (pc = msgBuf->mbtext, allUpper = TRUE; *pc && allUpper; pc++)
  1825.           {
  1826.           if (toUpper(*pc) != *pc)
  1827.           allUpper = FALSE;
  1828.  
  1829.           }
  1830.         if (allUpper)
  1831.         fakeFullCase(msgBuf->mbtext);
  1832.         putMessage(&logBuf);
  1833.  
  1834.         }
  1835.  
  1836.       }
  1837.     else
  1838.     fclose(qwkmsgfd);
  1839.  
  1840.     }
  1841.   while (tempcheck == 1);
  1842.   fclose(qwkmsgfd);
  1843.   return;
  1844.  
  1845.   }
  1846. /************************************************************************/
  1847. /*
  1848. * CleanUpPacket()
  1849. */
  1850. /*
  1851. */
  1852. /*
  1853. * This function deletes all files created in the QWKworkarea after
  1854. */
  1855. /*
  1856. * a packet is processed, good or bad.
  1857. */
  1858. /************************************************************************/
  1859. void
  1860. CleanUpPacket()
  1861.   {
  1862.   char      tempstr[30],
  1863.   tempstr2[100];
  1864.   int       rover;
  1865.   strcpy(tempstr2, (char *)&cfg.holdArea); /* (cfg.codeBuf + cfg.QWKWorkArea.saDirname)); */
  1866.   rover = strlen(tempstr2);
  1867.   tempstr2[rover - 1] = NULL;
  1868.   /*
  1869.   * printf("%s\n", tempstr2);
  1870.   */
  1871.   if (chdir(tempstr2) != 0) printf("chdir failed!\n");
  1872.   /*
  1873.   * printf("%s\n", getcwd(NULL, 100));
  1874.  iChar();
  1875.   *
  1876.   */
  1877.   getcwd(tempstr2, 100);
  1878.   printf("Current Directory: %s\n ", tempstr2);
  1879.   for (rover = 0; rover < MAXROOMS; rover++)
  1880.     {
  1881.     if (UsedQwkRooms[rover].messagesfound != 0)
  1882.       {
  1883.       sprintf(tempstr, "%03d.ndx", rover);
  1884.       unlink(tempstr);
  1885.  
  1886.       }
  1887.  
  1888.     }
  1889.   strcpy(tempstr, "personal.ndx");
  1890.   unlink(tempstr);
  1891.   sprintf(tempstr, "messages.dat");
  1892.   unlink(tempstr);
  1893.   sprintf(tempstr, "control.dat");
  1894.   unlink(tempstr);
  1895.   sprintf(tempstr, "%s.qwk", (cfg.codeBuf + cfg.nodeTitle));
  1896.   unlink(tempstr);
  1897.  
  1898.   }
  1899.  
  1900.